var XWindow=function(conf){
	var winHtml, defaults = { modal:true, renderCloser: true, title:'' }, self = this;
	this.conf = {};
	$.extend(this.conf, defaults, conf);
	
	winHtml = '<div class="window">';
	if (this.conf.renderCloser) winHtml += '<a href="#" title="Close window" class="button no-text window-closer"><span class="right"></span><span class="left"></span><span class="inner"><span class="icon icon-close-window"></span></span></a>';

	winHtml += '<div class="window-title"></div><div class="window-content"></div></div>';
	this.el = $(winHtml).hide(); 
	$('body').append(this.el); 

	this.title = this.el.find('.window-title');			// $ el - window title
	this.content = this.el.find('.window-content');		// $ el - window content
	this.windowCloser = this.el.find('.window-closer');	// $ el - window closer
	
	this.el.click(function(e){ e.stopPropagation(); });
	
	if (this.conf.draggable !== false){
		this.el.draggable({ containment: 'body', handle :'.window-title' });
		this.title.css('cursor', 'move');
	}
	
	if (typeof this.conf.content == 'object' && this.conf.content.length){
		this.content.append(this.conf.content);
		this.conf.content.css('display','');
		var data = this.conf.content.data();
		if (data && data.width) this.el.width(data.width||'auto');
	} 
	else if (typeof this.conf.content == 'string') this.content.html(this.conf.content);
	
	if (!this.conf.title.length && this.conf.content.length){
		this.conf.title = this.conf.content.attr('title');
		this.conf.content.removeAttr('title');
	}
	this.title.html(this.conf.title);
	
	this.windowCloser.off('click').on('click', function(){ self.hide.call(self); return false; });
	
	// Add buttons
	if (this.conf.buttons && this.conf.buttons.length>0){
		var i=0
			,bl = this.conf.buttons.length
			,buttons			// $ html object of buttons
			,btnConf			// temp config button
			,btn;				// temp button $ object

		buttons = $('<div class="buttons"></div>');
		
		for (; i<bl; i++){
			btnConf = this.conf.buttons[i];
			btn = $('<button>'+btnConf.text+'</button>');
			if (btnConf.cls) btn.addClass(btnConf.cls);
			if (btnConf.disabled == true) btn.attr('disabled', 'disabled').addClass('disabled');
			if (!btnConf.scope) btnConf.scope = this.content;
			
			if (!btnConf.fn) btn.on('click', $.proxy(this.hide, this));
			else {
				btn.on('click', { content: this.content, btn: btnConf, win: this }, function(e){
					var conf = e.data.btn, win = e.data.win, content = e.data.content, form = content.find('form'), formData = {};
					if (form.length) formData = win.serializeForm(form);
					if (conf.fn.call(conf.scope, content, form, formData) !== false) win.hide.call(win);
				});
				
			}			
			buttons.append(btn);		// append button to the buttons element
		}
		this.content.append(buttons);	// append buttons to the window content
	}
	
	return this;
};
XWindow.toString = function(){return 'XWERX Window Component';};


XWindow.prototype.setTitle = function(title){ if (title&&title.length) this.title.html(title); };


/**
 * jQuery-based serialization. Serializes a form to an object of { name:value }
 * @param form		jQuery form object
 * @param noEmpty	if true - return only non-empty values (0 is considered a non-empty value)
 * @returns 		js object: { name1: value1, ... }
 */
XWindow.prototype.serializeForm = function(form, noEmpty){
	var arr=form.serializeArray(),obj={},i=0,item;
	if (noEmpty){ for (; item=arr[i++] ;) if (typeof item.value !== 'undefined') obj[item.name] = item.value; }
	else for (; item=arr[i++] ;) obj[item.name] = item.value;
	return obj;
};



/**
 * Shows the window. 
 */
XWindow.prototype.scale = function(now, fx){ now=now<.5?.5:now; $(fx.elem).css({ '-webkit-transform': 'scale('+now+')', '-moz-transform': 'scale('+now+')', 'transform': 'scale('+now+')' }); };

XWindow.prototype.show = function(){
	if (!this.el) return;
	if (this.conf.modal) this.maskShow(); 
	$(window)
		.on('resize', $.proxy(this.center, this))
		.on('keydown', $.proxy(this.onEscape, this));
	this.center();
	this.el.show().animate({ opacity: 1 }, { step: this.scale, duration: 300, easing: 'swing', complete: function(){
		var el = $(this), btn = el.find('.buttons .submit'), inp = el.find('input:visible');
		if (!inp.length) inp = btn;
		try{inp[0].focus();}catch(e){}
		try{inp[0].select();}catch(e){} 
	}});
	return this;
};


/**
 * Hides the window component
 */
XWindow.prototype.hide = function(){
	var self = this;
	if (this.conf.onClose) this.conf.onClose.fn.call(this.conf.onClose.scope);
	if (this.el && this.el.is(":visible")){
		if (this.el) this.el.animate({ opacity: 0 }, { step: this.scale, duration: 400, easing: 'swing', complete: function(){ 
			if(self.conf.disposable) $(this).remove(); else $(this).hide();
		}});
		if (this.mask) this.maskHide();
		$(window).off('resize', this.center).off('keydown', this.onEscape);
	}
	return this;
};


/**
 * Adds a keydown event. Hit esc to close the window 
 */
XWindow.prototype.onEscape = function(e){
	if ($('body>.menu:visible').length) return;										// don't hide window if there's a menu visible (menu will be hidden with first esc hit) 
	if (e.keyCode==27) this.hide(); 													// hide window
};



/**
 * Center the window on screen
 */
XWindow.prototype.center = function(){
	var l=($('body').innerWidth()/2)-(this.el.outerWidth()/2), t=($('html').innerHeight()/2)-(this.el.outerHeight()/2);
	this.el.css({ left: l<0?l=0:l, top: t<0?t=0:t });
	return this;
};



/**
 * Shows the mask under the window (if modal==true)
 */
XWindow.prototype.maskShow = function(){ 
	this.mask=$('#mask');
	if (!this.mask.length){ 
		var self=this; 
		this.mask=$('<div id="mask" class="window-mask"></div>').appendTo('body').one('click', function(){self.hide.call(self,true);}); 
	}
	this.mask.fadeTo(400, 0.7);
};	

XWindow.prototype.maskHide = function(){ if (!this.mask) return; this.mask.fadeTo(400,0,function(){ $(this).remove(); }); };
